#ifndef _OAUTHCREDENTIALS_HPP_
#define _OAUTHCREDENTIALS_HPP_

#include "jhdefs.hpp"
#include "net/URI.hpp"
#include "net/HTTPRequest.hpp"
#include "net/HTMLForm.hpp"

NET_NAMESPACE_BEGIN

class COAuth10Credentials
{
public:
	enum SignatureMethod// OAuth 1.0A Signature Method.
	{
		SIGN_PLAINTEXT, /// OAuth 1.0A PLAINTEXT signature method
		SIGN_HMAC_SHA1  /// OAuth 1.0A HMAC-SHA1 signature method
	};

	COAuth10Credentials();
	COAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret);
	COAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret);
	explicit COAuth10Credentials(const CHTTPRequest& request);
	~COAuth10Credentials();

	void setConsumerKey(const std::string& consumerKey);
	const std::string& getConsumerKey() const;

	void setConsumerSecret(const std::string& consumerSecret);
	const std::string& getConsumerSecret() const;

	void setToken(const std::string& token);
	const std::string& getToken() const;

	void setTokenSecret(const std::string& tokenSecret);
	const std::string& getTokenSecret() const;

	void setRealm(const std::string& realm);
	const std::string& getRealm() const;

	void setCallback(const std::string& uri);
	const std::string& getCallback() const;

	void authenticate(CHTTPRequest& request, const CURI& uri, SignatureMethod method = SIGN_HMAC_SHA1);
	void authenticate(CHTTPRequest& request, const CURI& uri, const CHTMLForm& params, SignatureMethod method = SIGN_HMAC_SHA1);

	bool verify(const CHTTPRequest& request, const CURI& uri);
	bool verify(const CHTTPRequest& request, const CURI& uri, const CHTMLForm& params);

	void nonceAndTimestampForTesting(const std::string& nonce, const std::string& timestamp);

	static const std::string SCHEME;

protected:
	void signPlaintext(CHTTPRequest& request) const;
	void signHMACSHA1(CHTTPRequest& request, const std::string& uri, const CHTMLForm& params) const;
	std::string createNonce() const;
	std::string createSignature(const CHTTPRequest& request, const std::string& uri, const CHTMLForm& params, const std::string& nonce, const std::string& timestamp) const;

	static std::string percentEncode(const std::string& str);
	
private:
	COAuth10Credentials(const COAuth10Credentials&);
	COAuth10Credentials& operator = (const COAuth10Credentials&);

	std::string m_consumerKey;
	std::string m_consumerSecret;
	std::string m_token;
	std::string m_tokenSecret;
	std::string m_callback;
	std::string m_realm;
	std::string m_nonce;
	std::string m_timestamp;
};


NET_NAMESPACE_END

#endif
